/*
 * @Author: liusheng
 * @Date: 2022-04-11 15:13:10
 * @LastEditors: liusheng
 * @LastEditTime: 2022-04-11 16:05:31
 * @Description: 
 * email:liusheng613@126.com
 * Copyright (c) 2022 by liusheng/liusheng, All Rights Reserved. 
 * 
 剑指 Offer II 021. 删除链表的倒数第 n 个结点
给定一个链表，删除链表的倒数第 n 个结点，并且返回链表的头结点。

 

示例 1：
输入：head = [1,2,3,4,5], n = 2
输出：[1,2,3,5]
示例 2：

输入：head = [1], n = 1
输出：[]
示例 3：

输入：head = [1,2], n = 1
输出：[1]
 

提示：

链表中结点的数目为 sz
1 <= sz <= 30
0 <= Node.val <= 100
1 <= n <= sz
 

进阶：能尝试使用一趟扫描实现吗？


 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };

 

注意：本题与主站 19 题相同： https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/
 */

struct ListNode {
      int val;
      ListNode *next;
      ListNode() : val(0), next(nullptr) {}
      ListNode(int x) : val(x), next(nullptr) {}
      ListNode(int x, ListNode *next) : val(x), next(next) {}
};

//slow fast two point
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode * left = head;
        ListNode * right = head; 

        for (int i = 0; i < n; ++i)
        {
            right = right->next;
        }

        ListNode * beforeLeft = nullptr;
        //while end while
        //left is the node to be deleted
        while (right)
        {
            beforeLeft = left;
            left =left->next;
            right = right->next;
        }

        if (beforeLeft != nullptr)
        {
            ListNode * afterDeletedNode = left->next;
            delete left;
            beforeLeft->next = afterDeletedNode;
            return head;
        }
        else
        {
            ListNode * next = head->next;
            delete head;
            return next;
        }
        
    }
};

//slow fast two point
//same as above
class Solution2 {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        if (!head)
        {
            return head;
        }
        
        ListNode* slow = head;
        ListNode* fast = head;
        while (n--)
        {
            fast = fast->next;
        }
        
        ListNode * beforeDeleted = nullptr;
        //after while,slow is node to bedeletd
        while (fast)
        {
            beforeDeleted = slow;
            slow = slow->next;
            fast = fast->next;
        }
        
        if (slow == head)
        {
            head = head->next;
        }
        else
        {
            beforeDeleted->next = slow->next;
        }
        delete slow;
        return head;
    }
};
